const express = require("express"); //express
const cors = require("cors"); //跨域
const bodyParser = require("body-parser"); //获取body
const joi = require("joi"); //表单校验
// const multipart = require('connect-multiparty'); //解析multipart/form-data
// const multipartMiddleware = multipart(); // 加载 multipartMiddleware
/*
  数据解析小知识
  1、www-form-urlencoded  post请求默认提交的就是这种格式 配置bodyParser.json({ limit: '5000mb' })中间件即可
  2、form-data enctype="multipart/form-data"文件上传  需要 connect-multiparty中间件解析
  app.post('/formdata',multipartMiddleware, function (req, res) { console.log(req.body) });
  3、application/json content-type=application/json 配置 bodyParser.json({ limit: '5000mb' })中间件即可
*/

//导入路由每个路由模块
const userRouter = require("./router/user");
const adminRouter = require("./router/admin");
const adminProRouter = require("./router/adminpro");
const commonRouter = require("./router/common");

//解析 token 的中间件  // 导入解码配置文件
const expressJWT = require("express-jwt");
const config = require("./config");

// 创建 express 的服务器实例
const app = express();

// 路由前缀
const routerHD = '/api/v1'

// 将 cors 注册为全局中间件
app.use(cors());

// 响应数据的中间件 为了绑定res.cc方便下游使用  // 直接调用res.cc('成功',1) res.cc('失败',0)  res.cc(err)
app.use(function (req, res, next) {
  // status = 1 为成功； status = 0 为失败； 默认将 status 的值设置为 0，方便处理失败的情况
  res.cc = function (err, status = 0) {
    res.send({
      // 状态
      status,
      // 状态描述，判断 err 是 错误对象 还是 字符串
      message: err instanceof Error ? err.message : err,
    });
  };
  res.rt = function (obj) {
    if (typeof obj === 'string') {
      res.send({
        status: 1,
        message: obj
      })
    } else {
      obj.status = 1;
      res.send(obj)
    }
  }
  next();
});

// 使用 .unless({ path: [/^\/common\//] }) 指定哪些接口不需要进行 Token 的身份认证
//expressJWT 会自动解析token 绑定到req.user
app.use(
  expressJWT({
    secret: config.jwtSecretKey
  }).unless({
    path: [/^\/api\/v1\/common/, /^\/api\/v1\/uploads/]
  })
);

//注册中间件(获取body) // 数据大小限制
app.use(bodyParser.json({ limit: '5000mb', extended: true })); //添加json解析
app.use(bodyParser.urlencoded({ limit: '5000mb', extended: true })); //添加解析form表单 

//权限管理中间件
app.use(function (req, res, next) {
  if (req.user && req.user.username === 'admin') {
    //管理员模式
    // app.use(routerHD + "/admin", adminProRouter);
    app.use(routerHD + "/admin", adminRouter);
  } else {
    //普通模式
    app.use(routerHD + "/admin", adminRouter);
  }

  next();
})

//测试用的中间件
app.use(function (req, res, next) {
  next();
})

//过滤空格和字段
app.use(function (req, res, next) {
  let obj
  if (Object.keys(req.body).length) {
    obj = req.body
  } else {
    obj = req.query
  }
  for (const key in obj) {
    if (typeof obj[key] === 'string') {
      obj[key] = obj[key].trim()
      if (obj[key].length === 0) {
        delete obj[key]
      }
    }
  }
  next();
})

// 挂载路由
app.use(routerHD + "/user", userRouter);
app.use(routerHD + "/common", commonRouter);
// app.use(routerHD + "/admin", adminRouter);

//错误级别中间件 (捕获表单err)
app.use(function (err, req, res, next) {
  // 数据验证失败
  if (err instanceof joi.ValidationError) return res.cc(err);
  // 捕获身份认证失败的错误
  if (err.name === "UnauthorizedError") return res.cc("身份认证失败！");
  // 其他错误
  res.cc(err);
  next();
});

// 托管静态资源文件
app.use(routerHD + "/uploads", express.static("./uploads"));

// 调用 app.listen 方法，指定端口号并启动web服务器
app.listen(3007, function () {
  console.log("http://52xhl:3007/api/v1");
});